const { ccclass, property, executeInEditMode } = cc._decorator;
@ccclass
@executeInEditMode
export default class Helloworld extends cc.Component {
    start() {
        cc.debug.setDisplayStats(false);
        this.基础版教程_直接修改Sprite的_assembler();
        this.进阶版教程_自定义assembler替换掉Sprite的_assembler(5, 3, 3);
    }

    基础版教程_直接修改Sprite的_assembler() {
        let cocosNode = this.node.getChildByName('cocos');
        let cocosSpt = cocosNode.getComponent(cc.Sprite);
        cc.director.once(cc.Director.EVENT_AFTER_DRAW, () => {
            let assembler = cocosSpt['_assembler'];
            let renderData = assembler._renderData;
            let vDatas = renderData.vDatas[0];
            vDatas[0] = 100;       //左下角顶点x
            vDatas[1] = 700;       //左下角顶点y
            vDatas[5] = 500;       //右下角顶点x
            vDatas[6] = 800;       //右下角顶点y
            vDatas[10] = 200;      //左上角顶点x
            vDatas[11] = 1000;      //左上角顶点y
            vDatas[15] = 500;      //右上角顶点x
            vDatas[16] = 1000;      //右上角顶点y

            vDatas[2] = 0.3;       //左下角顶点u    
            vDatas[3] = 0.7;       //左下角顶点v
            vDatas[7] = 0.9;       //右下角顶点u
            vDatas[8] = 0.8;       //右下角顶点v
            vDatas[12] = 0.2;      //左上角顶点u
            vDatas[13] = 0.5;      //左上角顶点v
            vDatas[17] = 0.98;     //右上角顶点u
            vDatas[18] = 0.2;      //右上角顶点v

            let uintVDatas = renderData.uintVDatas[0];
            uintVDatas[4] = cc.color(0, 255, 0, 255)['_val'];        //左下角绿色
            uintVDatas[9] = cc.color(255, 0, 0, 0)['_val'];          //右下角红色，透明
            uintVDatas[14] = cc.color(255, 255, 0, 255)['_val'];    //左上角黄色
            uintVDatas[19] = cc.color(0, 0, 255, 0)['_val'];        //右上角蓝色，透明

            //设置标题顶点颜色
            let title = this.node.getChildByName('Title').getComponent(cc.Label);
            uintVDatas = title['_assembler']._renderData.uintVDatas[0];
            uintVDatas[4] = cc.Color.RED['_val'];                   //左下角红色
            uintVDatas[9] = cc.Color.RED['_val'];                   //右下角红色
            uintVDatas[14] = cc.Color.YELLOW['_val'];               //左上角黄色
            uintVDatas[19] = cc.Color.YELLOW['_val'];               //右上角黄色
        }, this);
    }

    进阶版教程_自定义assembler替换掉Sprite的_assembler(step: number, verticesCount: number, indicesCount: number) {
        //获取cc.Sprite对象ymSpt
        let ymSpt = this.node.getChildByName('ym').getComponent(cc.Sprite);
        //构造一个cc.Assembler对象，替换掉ymSpt原先4个顶点的那个_assembler
        let assembler = ymSpt['_assembler'] = new cc['Assembler']();
        //设置assembler的渲染对象是ymSpt，完成assembler和cc.Sprite双向绑定
        assembler.init(ymSpt);
        //构造一个renderData，用来存放顶点数据
        let renderData = new cc['RenderData']();
        //把assembler绑定到renderData，原生平台必须绑，Web平台绑不绑都行
        renderData.init(assembler);
        //根据顶点格式，创建renderData里的数组
        //step = 每个顶点占用长度，由顶点格式决定，cc.Sprite默认长度是5（x,y,u,v,color）
        //verticesCount = 顶点数量
        //indicesCount = 三角形数量 * 3
        let vertices = new Float32Array(verticesCount * step);
        let indices = new Uint16Array(indicesCount);
        renderData.updateMesh(0, vertices, indices);
        //原生平台可以用这个函数修改顶点格式，Web平台不需要
        cc.sys.isNative && assembler['setVertexFormat'](cc['gfx'].VertexFormat.XY_UV_Color);
        //通过assembler将renderData里的顶点数据提交给GPU渲染
        //原生平台并不会执行这个函数，因为原生平台引擎重载了fillBuffers
        assembler.fillBuffers = () => {
            let vData = renderData.vDatas[0];
            let iData = renderData.iDatas[0];
            let buffer = cc.renderer['_handle']._meshBuffer;
            let offsetInfo = buffer.request(verticesCount, indicesCount);
            let vertexOffset = offsetInfo.byteOffset >> 2;
            let vbuf = buffer._vData;
            if (vData.length + vertexOffset > vbuf.length) {
                vbuf.set(vData.subarray(0, vbuf.length - vertexOffset), vertexOffset);
            } else {
                vbuf.set(vData, vertexOffset);
            }
            let ibuf = buffer._iData;
            let indiceOffset = offsetInfo.indiceOffset;
            let vertexId = offsetInfo.vertexOffset;
            for (let i = 0, len = iData.length; i < len; ibuf[indiceOffset++] = vertexId + iData[i++]);
        }
        //更新renderData里的顶点数据
        assembler.updateRenderData = () => {
            let vData = renderData.vDatas[0];
            //设置顶点XY
            vData[0] = 0;
            vData[1] = 0;
            vData[5] = 500;
            vData[6] = 100;
            vData[10] = 200;
            vData[11] = 500;
            //设置顶点UV
            vData[2] = 0;
            vData[3] = 1;
            vData[7] = 1;
            vData[8] = 1;
            vData[12] = 0;
            vData[13] = 0;
            //设置顶点颜色
            let uintVData = renderData.uintVDatas[0];
            uintVData[4] = cc.Color.WHITE['_val'];
            uintVData[9] = cc.Color.WHITE['_val'];
            uintVData[14] = cc.Color.WHITE['_val'];
            //设置围成三角形的顶点索引顺序
            let iData = renderData.iDatas[0];
            iData[0] = 0;
            iData[1] = 1;
            iData[2] = 2;
        };
    }


}